home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Libraries / BlobMgr / Blob Manager Demo 4 / DemoTtt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-02-17  |  6.4 KB  |  341 lines  |  [TEXT/MACA]

  1. /*
  2.     Blob Manager Demonstration:  Tic-Tac-Toe
  3.     
  4.     25 July 1986    Paul DuBois
  5. */
  6.  
  7. # include    "BlobDemo.h"
  8. # include    <ControlMgr.h>
  9.  
  10.  
  11. # define    barWidth    3    /* board line size */
  12. # define    bSqSize        30    /* board square size */
  13. # define    pSqSize        28    /* playing piece square size */
  14. # define    yOffMesg    4
  15. # define    yOffPiece    24    /* offset of top of pieces */
  16. # define    xOffBoard    25
  17. # define    yOffBoard    59
  18. # define    xMid        73    /* xOffBoard + 1.5(bSqSize) + barWidth */
  19. # define    yOffBut        165
  20.  
  21.  
  22. static GrafPtr            tttPort;
  23. static BlobSetHandle    tttReceptors;    /* receptor blobs (board) */
  24. static BlobSetHandle    tttDonors;        /* donor blobs (pieces) */
  25. static BlobHandle        xBlob;            /* handles to each piece */
  26. static BlobHandle        oBlob;
  27.  
  28. static Boolean            haveWin;
  29. static Boolean            wait = false;
  30. static ControlHandle    restartCtl;
  31. static int                moves;
  32. static int                firstPlayer = 0;
  33. static Str255            statusStr;
  34.     
  35.  
  36. TttStatusMesg (s)
  37. Str255    s;
  38. {
  39. Rect    r;
  40.  
  41.     SetRect (&r, xMid-40, yOffMesg, xMid+40, yOffMesg+20);
  42.     TextBox    (s+1, (long) s[0], &r, 1);
  43.     StrCpy (statusStr, s);
  44. }
  45.  
  46.  
  47. TttGameOver (mesg)
  48. Str255    mesg;
  49. {
  50.     HiliteControl (restartCtl, 0);
  51.     TttStatusMesg (mesg);
  52.     wait = true;
  53. }
  54.  
  55.  
  56.  
  57. TttSelectPlayer    ()
  58. {
  59. BlobHandle    b;
  60. int            i;
  61.  
  62.     i = (moves + firstPlayer) % 2;       /* 0    = X, 1 = O */
  63.     HiliteBlob (GetBlobHandle (tttDonors, i), inFullBlob, normalDraw);
  64.     HiliteBlob (GetBlobHandle (tttDonors, 1 - i), inFullBlob, dimDraw);
  65.     if (i)
  66.         TttStatusMesg ("\pO's Move");
  67.     else
  68.         TttStatusMesg ("\pX's Move");
  69. /*
  70.     Freeze board except for positions occupied by current player and
  71.     empty positions.
  72.     This allows pieces to be played either by playing the piece at
  73.     the top, or by duplicating them on the board.  (Can't drag onto
  74.     another of own pieces, since replace transactions are disallowed.)
  75. */
  76.     ThawBlobSet (tttReceptors);
  77.     for (b = FirstBlob (tttReceptors); b != nil; b = NextBlob (b))
  78.     {
  79.         if (BGlob (b) != nil && BGlob (b) != GetBlobHandle (tttDonors, i))
  80.             FreezeBlob (b);
  81.     }
  82. }
  83.  
  84.  
  85. TttRestart ()
  86. {
  87.     HiliteControl (restartCtl, 255);
  88.     ZUnglueGlobSet (tttReceptors);
  89.     HiliteBlobSet (tttReceptors, inFullBlob, normalDraw);
  90.     moves =    0;
  91.     TttSelectPlayer    ();
  92.     wait = false;
  93. }
  94.  
  95.  
  96. /*
  97.     Dim the board positions that are not part of the win.  Dim them all
  98.     on "cat's game."
  99. */
  100.  
  101. TttShowWinner (pos)
  102. int    pos;
  103. {
  104. int    i;
  105. BlobHandle    b;
  106.  
  107.     for (i = 0; i < 9; ++i)
  108.     {
  109.         b = GetBlobHandle (tttReceptors, i);
  110.         if ((pos % 2) == 0)         /* this pos not part of win */
  111.             HiliteBlob (b, inFullBlob, dimDraw);    /* so dim it */
  112.         pos >>= 1;
  113.     }
  114. }
  115.  
  116. TttTestConfig (pos,    testPos)
  117. int    pos, testPos;
  118. {
  119. int    i;
  120. BlobHandle    b;
  121.  
  122.     if ((pos & testPos) == testPos) /*    have a win */
  123.     {
  124.         haveWin    = true;
  125.         TttShowWinner (testPos);
  126.     }
  127. }
  128.  
  129.  
  130. TttTestWin (b, boardPos)
  131. BlobHandle    b;
  132. int        boardPos;
  133. {
  134.     if (!haveWin)     /*    don't bother if    other player already won */
  135.     {
  136.         TttTestConfig (boardPos, 0x007); /*    top row    */
  137.         TttTestConfig (boardPos, 0x038); /*    middle row */
  138.         TttTestConfig (boardPos, 0x1c0); /*    bottom row */
  139.         TttTestConfig (boardPos, 0x049); /*    left column    */
  140.         TttTestConfig (boardPos, 0x092); /*    middle column */
  141.         TttTestConfig (boardPos, 0x124); /*    right column */
  142.         TttTestConfig (boardPos, 0x111); /*    diagonal */
  143.         TttTestConfig (boardPos, 0x054); /*    diagonal */
  144.         if (haveWin)
  145.         {
  146.             if (b == xBlob)
  147.             {
  148.                 TttGameOver ("\pX Wins"); /* loser goes    first next time    */
  149.                 firstPlayer = 1;
  150.             }
  151.             else
  152.             {
  153.                 TttGameOver ("\pO Wins");
  154.                 firstPlayer = 0;
  155.             }
  156.         }
  157.     }
  158. }
  159.  
  160.  
  161. TttBoardPos (b)
  162. BlobHandle    b;
  163. {
  164. int    i, mask, result;
  165. BlobHandle    b2;
  166.  
  167.     result = 0;
  168.     mask = 1;
  169.     for (i = 0; i < 9; ++i)
  170.     {
  171.         b2 = GetBlobHandle (tttReceptors, i);
  172.         if ((**b2).glob == b)         /* board occupied by desired piece    */
  173.             result |= mask;
  174.         mask <<= 1;
  175.     }
  176.     return (result);
  177. }
  178.  
  179.  
  180. TttCheckStatus ()
  181. {
  182. int    xbPos, obPos;
  183.  
  184.     haveWin = false;
  185.     xbPos = TttBoardPos (xBlob);
  186.     obPos = TttBoardPos (oBlob);
  187.     TttTestWin (xBlob, xbPos);
  188.     TttTestWin (oBlob, obPos);
  189.     if (!haveWin)             /* no win, but board might be full now */
  190.     {
  191.         if ((xbPos | obPos) == 0x1ff)
  192.         {
  193.             TttShowWinner (0);
  194.             TttGameOver ("\pCat's Game");
  195.             firstPlayer = 1 - firstPlayer; /* alternate on a draw */
  196.         }
  197.     }
  198. }
  199.  
  200.  
  201. TttMouse (pt, t, mods)
  202. Point    pt;
  203. long    t;
  204. int    mods;
  205. {
  206. int                result;
  207. ControlHandle    ctl;
  208.  
  209.     if (FindControl    (pt, tttPort, &ctl))
  210.     {
  211.         if (TrackControl (ctl, pt, nil))
  212.         {
  213.             TttRestart ();
  214.         }
  215.     }
  216.     else if    (!wait)
  217.     {
  218.         BlobClick (pt, t, tttDonors, tttReceptors);
  219.         result = BClickResult ();
  220.         if (result == bcGlue || result == bcDup)
  221.         {
  222.             ++moves;
  223.             TttCheckStatus ();
  224.             if (!wait)     /*    no win yet */
  225.             {
  226.                 TttSelectPlayer    ();
  227.             }
  228.         }
  229.     }
  230. }
  231.  
  232. TttUpdate (resized)
  233. Boolean    resized;
  234. {
  235.     DrawControls (tttPort);
  236.     TttStatusMesg (statusStr);
  237.     DrawGrid (3, 3,    xOffBoard, yOffBoard, bSqSize, bSqSize,    barWidth, barWidth);
  238.     DrawBlobSet (tttDonors);
  239.     DrawBlobSet (tttReceptors);
  240. }
  241.  
  242.  
  243. TttActivate    (active)
  244. Boolean    active;
  245. {
  246.     if (active)
  247.     {
  248.         SetDragRects (tttPort);
  249.         SetBCPermissions (false, false, true, false, false);
  250.     }
  251. }
  252.  
  253.  
  254. /*
  255.     Make receptor blobs
  256. */
  257.     
  258. TttMakeRBlob (r)
  259. Rect    *r;
  260. {
  261. BlobHandle    b;
  262.  
  263.     b = NewBlob (tttReceptors, false, 0, false, 0L);
  264.     OpenBlob ();
  265.     EraseRect (r);
  266.     InsetRect (r, 1, 1);
  267.     FrameRect (r);
  268.     InsetRect (r, 2, 2);
  269.     FrameRect (r);
  270.     InsetRect (r, -2, -2);
  271.     CloseRectBlob (b, r, r);
  272. }
  273.  
  274.  
  275. TttMakeReceptors ()
  276. {
  277.     tttReceptors =    NewBlobSet ();
  278.     MakeBlobGrid (3, 3, xOffBoard, yOffBoard, bSqSize, bSqSize,
  279.                     barWidth, barWidth, &TttMakeRBlob);
  280. }
  281.  
  282.  
  283. /*
  284.     Make donor blobs
  285. */
  286.  
  287. TttMakeDBlob (b, ch, x, y)
  288. BlobHandle    *b;
  289. int        ch, x, y;
  290. {
  291. Rect    r;
  292.  
  293.     *b = NewBlob (tttDonors, false, 9, false, 0L);
  294.     OpenBlob ();
  295.     SetRect (&r, 0, 0, pSqSize, pSqSize);
  296.     OffsetRect (&r, x, y);
  297.     EraseRect (&r);
  298.     PenSize    (2, 2);
  299.     FrameRect (&r);
  300.     PenNormal ();
  301.     MoveTo (r.left+pSqSize/2-4, r.bottom-pSqSize/2+5);
  302.     DrawChar ((char) ch);
  303.     CloseRectBlob (*b, &r, &r);
  304. }
  305.  
  306.  
  307. TttMakeDonors ()
  308. {
  309.     tttDonors = NewBlobSet ();
  310.     TttMakeDBlob (&xBlob, 'X', xMid-pSqSize-5, yOffPiece);
  311.     TttMakeDBlob (&oBlob, 'O', xMid+5, yOffPiece);
  312. }
  313.  
  314.  
  315. TttInit    ()
  316. {
  317. Rect    r;
  318.  
  319.     tttPort = GetDemoWind (tttWindRes);
  320.     SkelWindow (tttPort,
  321.                 TttMouse,        /* mouse clicks */
  322.                 nil,            /* key clicks */
  323.                 TttUpdate,        /* updates */
  324.                 TttActivate,    /* activate/deactivate events */
  325.                 nil,            /* close window */
  326.                 DoWClobber,        /* dispose of window */
  327.                 nil,            /* idle proc */
  328.                 false);            /* irrelevant, since no idle proc */
  329.  
  330.     TttMakeReceptors ();
  331.     TttMakeDonors ();
  332.     EnableBlobSet (tttReceptors);
  333.     EnableBlobSet (tttDonors);
  334.     SetRect (&r, xMid-45, yOffBut, xMid+45, yOffBut+20);
  335.     restartCtl = NewControl (tttPort, &r, "\pRestart", true, 0, 0, 0,
  336.                                 pushButProc, nil);
  337.     TttRestart ();
  338.     TttUpdate ();
  339.     ValidRect (&tttPort->portRect);
  340. }
  341.